package securityproject;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactoryConfigurationError;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;
import org.xml.sax.SAXException;

import securityproject.utils.Constants;
import securityproject.utils.RuleUtils;

public class EditRule extends HttpServlet {

	/**
	 * 
	 */
	private static final long serialVersionUID = -8164290679416541463L;
	private String ruleTypeParam;
	private String ruleScopeParam;
	private String filterTypeParam;
	private String ruleName;

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {

		createXMLRule(req);

		createXSLTRule();

		// delete old temp logs
		File tempLogsFolder = new File(Constants.TEMP_FOLDER);
		for (File tmpLog : tempLogsFolder.listFiles()) {
			tmpLog.delete();
		}

		resp.sendRedirect("../ManageRules.jsp?" + RuleUtils.RULE_SCOPE
				+ "=" + ruleScopeParam);
	}

	private void createXSLTRule() throws TransformerFactoryConfigurationError,
			IOException, FileNotFoundException {

		try {

			// Instantiate a DocumentBuilderFactory.
			DocumentBuilderFactory dfactory = DocumentBuilderFactory
					.newInstance();

			DocumentBuilder dBuilder = dfactory.newDocumentBuilder();

			TransformerFactory tFactory = TransformerFactory.newInstance();

			Document inDoc = null;
			try {
				inDoc = dBuilder.parse(RuleUtils.getXmlRule(ruleName));
			} catch (SAXException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			// activating suffix rules
			Transformer transformer = tFactory.newTransformer(new StreamSource(
					Constants.XML_RULES_TRANSFORMER));

			FileOutputStream out = getOutputRuleStream();
			transformer.transform(new DOMSource(inDoc), new StreamResult(out));

			out.flush();
			out.close();

		} catch (ParserConfigurationException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}

		catch (TransformerConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (TransformerException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private FileOutputStream getOutputRuleStream() throws FileNotFoundException {

		String fileName = filterTypeParam + "_" + ruleTypeParam + "_"
				+ ruleName;

		FileOutputStream out = new FileOutputStream(RuleUtils
				.getRuleFolder(ruleScopeParam, false)
				+ fileName + ".xslt");

		return out;
	}

	private void deleteOldRule(String ruleName) {

		// delete xml rule

		File xmlRule = new File(RuleUtils.getXmlRule(ruleName));

		xmlRule.delete();

		// delete xslt rule

		List<String> folders = new LinkedList<String>();

		File ruleScopeFolder = new File(Constants.XSL_FILTER_RULES_FOLDER);
		for (File ruleScope : ruleScopeFolder.listFiles()) {
			// active folder
			folders.add(RuleUtils.getRuleFolder(ruleScope.getName(),
					true));
			// inactive folder
			folders.add(RuleUtils.getRuleFolder(ruleScope.getName(),
					false));
		}

		String[] filterTypes = { "include", "exclude", "tagging" };

		String[] ruleTypes = { "normal", "custom" };

		for (String folder : folders) {
			for (String filterType : filterTypes) {
				for (String ruleType : ruleTypes) {

					File activeRuleFile = new File(folder + filterType + "_"
							+ ruleType + "_" + ruleName + ".xslt");
					if (activeRuleFile.exists()) {
						activeRuleFile.delete();
					}
				}
			}
		}
	}

	private void createXMLRule(HttpServletRequest req)
			throws TransformerFactoryConfigurationError, IOException {
		try {

			ruleName = req.getParameter("ruleName");
			
			deleteOldRule(req.getParameter("oldName"));

			DocumentBuilder dBuilder;
			// Instantiate a DocumentBuilderFactory.
			javax.xml.parsers.DocumentBuilderFactory dfactory = DocumentBuilderFactory
					.newInstance();
			dBuilder = dfactory.newDocumentBuilder();

			Document document = dBuilder.newDocument();

			// create base elemnt

			Element rule = document.createElement("rule");
			document.appendChild(rule);

			// set rule name

			Element name = document.createElement("name");
			rule.appendChild(name);

			Text nameText = document.createTextNode(req
					.getParameter("ruleName"));
			name.appendChild(nameText);

			// set rule description

			Element description = document.createElement("description");
			rule.appendChild(description);

			Text descriptionText = document.createTextNode(req
					.getParameter("ruleDescription"));
			description.appendChild(descriptionText);

			// set rule scope

			Element ruleScope = document.createElement("ruleScope");
			rule.appendChild(ruleScope);

			ruleScopeParam = req.getParameter("ruleScope");
			Text ruleScopeText = document.createTextNode(ruleScopeParam);
			ruleScope.appendChild(ruleScopeText);

			// set rule type

			Element ruleType = document.createElement("ruleType");
			rule.appendChild(ruleType);

			ruleTypeParam = req.getParameter("ruleType");
			Text ruleTypeText = document.createTextNode(ruleTypeParam);
			ruleType.appendChild(ruleTypeText);

			// set rule filter type

			Element filterType = document.createElement("filterType");
			rule.appendChild(filterType);

			filterTypeParam = req.getParameter("filterType");
			Text filterTypeText = document.createTextNode(filterTypeParam);
			filterType.appendChild(filterTypeText);

			// set rule tag name

			Element tagName = document.createElement("tagName");
			rule.appendChild(tagName);

			String tagNameParam = req.getParameter("tagName");
			if (tagNameParam == null) {
				tagNameParam = "";
			}

			Text tagNameText = document.createTextNode(tagNameParam);
			tagName.appendChild(tagNameText);

			if (!req.getParameter("ruleType").equals("custom")) {

				// add filters

				int i = 0;
				while (req.getParameter("fieldName" + i) != null) {

					// add base filter element

					Element filter = document.createElement("filter");
					rule.appendChild(filter);

					// add filter field name

					Element fieldName = document.createElement("fieldName");
					filter.appendChild(fieldName);

					Text fieldNameText = document.createTextNode(req
							.getParameter("fieldName" + i));
					fieldName.appendChild(fieldNameText);

					// add filter method

					Element filterMethod = document
							.createElement("fieldMethod");
					filter.appendChild(filterMethod);

					Text filterMethodText = document.createTextNode(req
							.getParameter("filterMethod" + i));
					filterMethod.appendChild(filterMethodText);

					// add expression value

					Element expression = document.createElement("expression");
					filter.appendChild(expression);

					Text expressionText = document.createTextNode(req
							.getParameter("expression" + i));
					expression.appendChild(expressionText);

					i++;

				}
			} else {

			}

			RuleUtils.writeXML(ruleName, document);

		} catch (ParserConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();

		} catch (TransformerConfigurationException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();

		} catch (TransformerException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();

		}
	}
}
